/*
 * ShemTextReaderTestHelper.java
 *
 * Created on October 16, 2002, 2:31 PM
 *
 * Copyright (c) 2002 The General Electric Company
 */

package com.ge.healthcare.autosc.processor.shemjob.test;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;

import junit.framework.Assert;

import com.ge.healthcare.autosc.common.exceptions.BasicException;
import com.ge.healthcare.autosc.processor.magmon.MagnetMonitorUtility;
import com.ge.healthcare.autosc.processor.shemjob.reader.ShemTextReader;

/**
 * Class that provides help in testing objects that implement the
 *  ShemTextReader interface.
 *
 * @author Daniel S. Horwitz, Compuware Corp.
 *
 * @version AutoSC P5P6
 */
public class ShemTextReaderTestHelper
{
    /** The JUnit test helper to be used by this class.  */
    private TestHelper thelper = null;

    /**
     * Constructs a test helper.
     */
    public ShemTextReaderTestHelper()
    {
        this( new TestHelper() );
    }

    /**
     * Constructs a test helper using the specified JUnit test helper.
     *
     * @param myJUnitHelper The JUnit test helper to be used by this class.
     */
    public ShemTextReaderTestHelper( TestHelper myJUnitHelper )
    {
        super();
        thelper = myJUnitHelper;
    }

    /**
     * Test a class that implements ShemTextReader for valid operation.
     *  This exercises the methods in the ShemTextReader interface.  This
     *  reads the specified source file and compares the results of the
     *  readLine() method against the contents of the expected results file.
     *
     * @param uut The class being tested.
     *
     * @param sourceRelPath Relative path from this directory to the source
     *  file.
     *
     * @param expectedRelPath Relative path from this directory to the
     *  expected results file.
     *
     * @exception AscServiceAbortException If an unexpected error is detected.
     */
    public void checkValidOperation( ShemTextReader uut,
                                     String sourceRelPath,
                                     String expectedRelPath )
        throws BasicException
    {
        File myHomeDir = getHomeDirectory();
        File sourceFile = new File( myHomeDir, sourceRelPath );
        File expectedFile = new File( myHomeDir, expectedRelPath );
        helpCheckValidOperation( uut, sourceFile, expectedFile, false );
        helpCheckValidOperation( uut, sourceFile, expectedFile, true );
    }

    /**
     * Help test a class that implements ShemTextReader for valid operation.
     *  This exercises the methods in the ShemTextReader interface.  This
     *  reads the specified source file and compares the results of the
     *  readLine() method against the contents of the expected results file.
     *
     * @param uut The class being tested.
     *
     * @param sourceFile The source file.
     *
     * @param expectedFile The expected results file.
     *
     * @param useSilentClose True if using silentlyClose(), false if
     *  using close().
     *
     * @exception AscServiceAbortException If an unexpected error is detected.
     */
    public void helpCheckValidOperation( ShemTextReader uut,
                                         File sourceFile,
                                         File expectedFile,
                                         boolean useSilentClose )
        throws BasicException
    {
        InputStream rawSource = thelper.createInputStreamFor( sourceFile );
        MagnetMonitorUtility utility = new MagnetMonitorUtility();
        uut.open( "TestReaderId", rawSource, utility, null );
        BufferedReader expectedReader =
            thelper.createBufferedReaderFor( expectedFile );
        try
        {
            String actualLine = "dummy";
            String expectedLine = "dummy";
            while ( actualLine != null )
            {
                actualLine = uut.readLine();
                expectedLine = expectedReader.readLine();
                Assert.assertEquals( "Files differ:",
                                     expectedLine,
                                     actualLine );
            }
            expectedReader.close();
        }
        catch ( IOException e )
        {
            throw new BasicException( e.toString() );
        }
        if ( useSilentClose )
        {
            uut.silentlyClose();
        }
        else
        {
            uut.close();
        }
    }

    /**
     * Generate a results file for the specified input file and the
     *  specified text reader.  The results file will be checked and then
     *  used as the expected results for the a test that uses the
     *  checkValidOperation() method, above.
     *
     * @param uut The class being tested.
     *
     * @param sourceRelPath Relative path from this directory to the
     *  source file.
     *
     * @param resultsRelPath Relative path from this directory to the
     *  results file.
     *
     * @exception AscServiceAbortException If an unexpected error is detected.
     */
    public void genResultsFile( ShemTextReader uut,
                                String sourceRelPath,
                                String resultsRelPath )
        throws BasicException
    {
        File myHomeDir = getHomeDirectory();
        File sourceFile = new File( myHomeDir, sourceRelPath );
        File resultsFile = new File( myHomeDir, resultsRelPath );
        InputStream rawSource = thelper.createInputStreamFor( sourceFile );
        MagnetMonitorUtility utility = new MagnetMonitorUtility();
        uut.open( "TestReaderId", rawSource, utility, null );
        try
        {
            OutputStream rawOutput = new FileOutputStream( resultsFile );
            PrintWriter myWriter =
                new PrintWriter( new BufferedOutputStream( rawOutput ) );
            for ( String currentLine = uut.readLine();
                  currentLine != null;
                  currentLine = uut.readLine() )
            {
                myWriter.println( currentLine );
            }
            Assert.assertTrue( "Error writing", !myWriter.checkError() );
            myWriter.close();
            uut.close();
        }
        catch ( IOException e )
        {
            throw new BasicException( e.toString() );
        }
    }

    /**
     * Test a class that implements ShemTextReader for handling a corrupt
     *  input stream.  The corrupt input stream has either been truncated or
     *  has a content error.
     *
     * @param uut The class being tested.
     *
     * @param sourceRelPath Relative path from this directory to the
     *  source file.
     *
     * @param bytesUntilFailure The number of bytes of the source file which
     *  may be read successfully.  Once this limit is reached, the failure
     *  condition is triggered.
     *  If this value is zero, the source file will be read without failure.
     *
     * @param endOfStreamOnFailure This determines what to do when the
     *  failure condition on reading the source file is triggered.
     *  If true, act like the end of the stream has been reached when the
     *  failure condition is triggered.  If false, act like an I/O error
     *  has been detected when the failure condition is triggered.
     *
     * @param expectedMessage The error message expected to be generated.
     *
     * @exception AscServiceAbortException If an unexpected error is detected.
     */
    public void checkCorruptInput( ShemTextReader uut,
                                   String sourceRelPath,
                                   int bytesUntilFailure,
                                   boolean endOfStreamOnFailure,
                                   String expectedMessage )
        throws BasicException
    {
        File myHomeDir = getHomeDirectory();
        File sourceFile = new File( myHomeDir, sourceRelPath );
        InputStream rawSource = thelper.createInputStreamFor( sourceFile );
        if ( bytesUntilFailure != 0 )
        {
            rawSource = new FailingInputFilterStream( rawSource,
                                                      bytesUntilFailure,
                                                      endOfStreamOnFailure );
        }
        Object[][] myStubControl = new Object[][] {
            new Object[] { "AscServiceHelper",
                           "issueWarningTo",
                           "TestReaderId not a whole number of binary records",
                           "shemteam" }
        };
        thelper.defineStubControl( myStubControl );
        MagnetMonitorUtility utility = new MagnetMonitorUtility();
        uut.open( "TestReaderId", rawSource, utility, null );
        String actualLine = "dummy";
        while ( actualLine != null )
        {
            try
            {
                actualLine = uut.readLine();
            }
            catch ( BasicException wantedError )
            {
            	if(wantedError.getErrorCode() != null) {
	            	Assert.assertEquals( "Error code is not expected:",
	                        expectedMessage,
	                        wantedError.getErrorCode() );
            	} else {
            		Assert.assertEquals( "Error code is not expected:",
	                        expectedMessage,
	                        wantedError.getMessage() );
            	}
                uut.silentlyClose();
                return;
            }
        }
        uut.silentlyClose();
        Assert.assertTrue( "Was expecting error, but none detected.", false );
    }

    /**
     * Test a class that implements ShemTextReader for handling I/O errors
     *  while closing the input stream.
     *
     * @param uut The class being tested.
     *
     * @param sourceRelPath Relative path from this directory to the
     *  source file.
     *
     * @param expectedMessage The error message expected to be generated.
     *
     * @exception AscServiceAbortException If an unexpected error is detected.
     */
    public void checkCloseFailures( ShemTextReader uut,
                                    String sourceRelPath,
                                    String expectedMessage )
        throws BasicException
    {
        commonPartCheckCloseFailures( uut, sourceRelPath );
        try
        {
            uut.close();
            Assert.assertTrue( "Was expecting error, but none detected.", false );
        }
        catch ( BasicException wantedError )
        {
            Assert.assertEquals( "Text of error not as expected:",
                                 expectedMessage,
                                 wantedError.toString() );
        }
        commonPartCheckCloseFailures( uut, sourceRelPath );
        uut.silentlyClose();
    }

    /**
     * The common part of testing a class that implements ShemTextReader for
     *  handling I/O errors while closing the input stream.  This reads the
     *  file using an input stream that will get an IOException when it is
     *  closed.  The input is read up to the end of the file before returning.
     *
     * @param uut The class being tested.
     *
     * @param sourceRelPath Relative path from this directory to the
     *  source file.
     *
     * @exception AscServiceAbortException If an unexpected error is detected.
     */
    private void commonPartCheckCloseFailures( ShemTextReader uut,
                                               String sourceRelPath )
        throws BasicException
    {
        File myHomeDir = getHomeDirectory();
        File sourceFile = new File( myHomeDir, sourceRelPath );
        InputStream rawSource = thelper.createInputStreamFor( sourceFile );
        rawSource = new CloseErrorInputFilterStream( rawSource );
        MagnetMonitorUtility utility = new MagnetMonitorUtility();
        uut.open( "TestReaderId", rawSource, utility, null );
        String actualLine = "dummy";
        while ( actualLine != null )
        {
           actualLine = uut.readLine();
        }
    }

    /**
     * Test a class that implements ShemTextReader for handling reading when
     *  the reader is not open.
     *
     * @param uut The class being tested.
     *
     * @param sourceRelPath Relative path from this directory to the
     *  source file.
     *
     * @param expectedMessage The error message expected to be generated.
     *
     * @exception AscServiceAbortException If an unexpected error is detected.
     */
    public void checkReadWhenNotOpen( ShemTextReader uut,
                                      String sourceRelPath,
                                      String expectedMessage )
        throws BasicException
    {
        try
        {
            uut.readLine();
            Assert.assertTrue( "Was expecting error, but none detected.", false );
        }
        catch ( BasicException beforeOpen )
        {
        	Assert.assertEquals( "Text of error not as expected:",
                                 expectedMessage,
                                 beforeOpen.toString());
        }
        File myHomeDir = getHomeDirectory();
        File sourceFile = new File( myHomeDir, sourceRelPath );
        InputStream rawSource = thelper.createInputStreamFor( sourceFile );
        MagnetMonitorUtility utility = new MagnetMonitorUtility();
        uut.open( "TestReaderId", rawSource, utility, null );
        String actualLine = "dummy";
        while ( actualLine != null )
        {
           actualLine = uut.readLine();
        }
        uut.close();
        try
        {
            uut.readLine();
            Assert.assertTrue( "Was expecting error, but none detected.", false );
        }
        catch ( BasicException afterClose )
        {
            Assert.assertEquals( "Text of error not as expected:",
                                 expectedMessage,
                                 afterClose.toString() );
        }
    }

    /**
     * Get the home directory, which is the directory containing this Java
     *  source file.
     *
     * @return The home directory.
     */
    private File getHomeDirectory()
    {
        String relPath =
            "/src/java/com/ge/healthcare/autosc/processor/shemjob/reader/test";
        thelper.setRelPathToHomeDirectory( relPath );
        return thelper.getHomeDirectory();
    }
}
